home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / SaveWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  18.2 KB  |  951 lines

  1. /*
  2. **    SaveWindow.c
  3. **
  4. **    Support routines for saving IFF-ILBM files
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* Current compression mode. */
  17.  
  18. #define DUMP        0
  19. #define RUN            1
  20.  
  21.     /* ByteRun compression data. */
  22.  
  23. #define MINRUN        3
  24. #define MAXRUN        128
  25. #define MAXDAT        128
  26.  
  27.     /* Chunk types. */
  28.  
  29. #define ID_ILBM        MAKE_ID('I','L','B','M')
  30. #define ID_ANNO        MAKE_ID('A','N','N','O')
  31. #define ID_BMHD        MAKE_ID('B','M','H','D')
  32. #define ID_CMAP        MAKE_ID('C','M','A','P')
  33. #define ID_CAMG        MAKE_ID('C','A','M','G')
  34. #define ID_BODY        MAKE_ID('B','O','D','Y')
  35.  
  36.     /* Masking technique. */
  37.  
  38. #define mskNone        0
  39.  
  40.     /* Compression techniques. */
  41.  
  42. #define cmpNone        0
  43. #define cmpByteRun1    1
  44.  
  45.     /* A bitmap header. */
  46.  
  47. typedef struct
  48. {
  49.     UWORD        w,h;                    /* raster width & height in pixels */
  50.     WORD        x,y;                    /* position for this image */
  51.     UBYTE        nPlanes;                /* # source bitplanes */
  52.     UBYTE        masking;                /* masking technique */
  53.     UBYTE        compression;            /* compression algorithm */
  54.     UBYTE        pad1;                    /* UNUSED.  For consistency, put 0 here.*/
  55.     UWORD        transparentColor;        /* transparent "color number" */
  56.     UBYTE        xAspect,yAspect;        /* aspect ratio, a rational number x/y */
  57.     WORD        pageWidth,pageHeight;    /* source "page" size in pixels */
  58. } BitMapHeader;
  59.  
  60.     /* A single 8-bit colour register. */
  61.  
  62. typedef struct
  63. {
  64.     UBYTE        red,                    /* red component, 0..255 */
  65.                 green,                    /* green component, 0..255 */
  66.                 blue;                    /* blue component, 0..255 */
  67. } ColorRegister;
  68.  
  69.     /* Local packer data. */
  70.  
  71. STATIC LONG        PackedBytes;
  72. STATIC BYTE        Buffer[MAXDAT + 1];
  73.  
  74.     /* PutDump(PLANEPTR Destination,LONG Count):
  75.      *
  76.      *    Output a byte dump.
  77.      */
  78.  
  79. STATIC PLANEPTR
  80. PutDump(PLANEPTR Destination,LONG Count)
  81. {
  82.     PLANEPTR Source = Buffer;
  83.  
  84.     *Destination++ = Count - 1;
  85.  
  86.     PackedBytes += Count + 1;
  87.  
  88.     while(Count--)
  89.         *Destination++ = *Source++;
  90.  
  91.     return(Destination);
  92. }
  93.  
  94.     /* PutRun(PLANEPTR Destination,LONG Count,WORD Char):
  95.      *
  96.      *    Output a byte run.
  97.      */
  98.  
  99. STATIC PLANEPTR
  100. PutRun(PLANEPTR Destination,LONG Count,WORD Char)
  101. {
  102.     *Destination++ = -(Count - 1);
  103.     *Destination++ = Char;
  104.  
  105.     PackedBytes += 2;
  106.  
  107.     return(Destination);
  108. }
  109.  
  110.     /* PackRow(PLANEPTR *SourcePtr,PLANEPTR Destination,LONG RowSize):
  111.      *
  112.      *    Pack a row of bitmap data using ByteRun compression,
  113.      *    based on the original "EA IFF 85" pack.c example code.
  114.      */
  115.  
  116. STATIC LONG
  117. PackRow(PLANEPTR *SourcePtr,PLANEPTR Destination,LONG RowSize)
  118. {
  119.     PLANEPTR Source;
  120.     LONG Buffered,RunStart;
  121.     LONG Mode,LastChar,Char;
  122.  
  123.     Source        = *SourcePtr;
  124.     Buffered    = 1,
  125.     RunStart    = 0;
  126.     Mode        = DUMP;
  127.  
  128.     PackedBytes = 0;
  129.  
  130.     Buffer[0] = LastChar = Char = *Source++;
  131.  
  132.     RowSize--;
  133.  
  134.     while(RowSize--)
  135.     {
  136.         Buffer[Buffered++] = Char = *Source++;
  137.  
  138.         if(Mode)
  139.         {
  140.             if((Char != LastChar) || (Buffered - RunStart > MAXRUN))
  141.             {
  142.                 Destination    = PutRun(Destination,Buffered - 1 - RunStart,LastChar);
  143.                 Buffer[0]    = Char;
  144.                 Buffered    = 1;
  145.                 RunStart    = 0;
  146.                 Mode        = DUMP;
  147.             }
  148.         }
  149.         else
  150.         {
  151.             if(Buffered > MAXDAT)
  152.             {
  153.                 Destination    = PutDump(Destination,Buffered - 1);
  154.                 Buffer[0]    = Char;
  155.                 Buffered    = 1;
  156.                 RunStart    = 0;
  157.             }
  158.             else
  159.             {
  160.                 if(Char == LastChar)
  161.                 {
  162.                     if(Buffered - RunStart >= MINRUN)
  163.                     {
  164.                         if(RunStart)
  165.                             Destination = PutDump(Destination,RunStart);
  166.  
  167.                         Mode = RUN;
  168.                     }
  169.                     else
  170.                     {
  171.                         if(!RunStart)
  172.                             Mode = RUN;
  173.                     }
  174.                 }
  175.                 else
  176.                     RunStart = Buffered - 1;
  177.             }
  178.         }
  179.  
  180.         LastChar = Char;
  181.     }
  182.  
  183.     if(Mode)
  184.         PutRun(Destination,Buffered - RunStart,LastChar);
  185.     else
  186.         PutDump(Destination,Buffered);
  187.  
  188.     *SourcePtr = Source;
  189.  
  190.     return(PackedBytes);
  191. }
  192.  
  193.     /* PutANNO(struct IFFHandle *Handle):
  194.      *
  195.      *    Output `ANNO' chunk.
  196.      */
  197.  
  198. STATIC BOOL
  199. PutANNO(struct IFFHandle *Handle)
  200. {
  201.     extern UBYTE __far VersTag[];
  202.  
  203.     LONG Len;
  204.     LONG Error;
  205.  
  206.     Len = strlen(&VersTag[1]);
  207.  
  208.         /* Push the `ANNO' chunk on the stack. */
  209.  
  210.     if(!(Error = PushChunk(Handle,0,ID_ANNO,Len)))
  211.     {
  212.             /* Write the creator string. */
  213.  
  214.         if(WriteChunkBytes(Handle,&VersTag[1],Len) == Len)
  215.         {
  216.                 /* Pop the `ANNO' chunk. */
  217.  
  218.             if(!(Error = PopChunk(Handle)))
  219.                 return(TRUE);
  220.         }
  221.         else
  222.             Error = IoErr();
  223.     }
  224.  
  225.     SetIoErr(Error);
  226.  
  227.     return(FALSE);
  228. }
  229.  
  230.     /* PutBMHD():
  231.      *
  232.      *    Output `BMHD' chunk.
  233.      */
  234.  
  235. STATIC BOOL
  236. PutBMHD(struct IFFHandle *Handle,struct Window *Window,UBYTE Compression,LONG Left,LONG Top,LONG Width,LONG Height)
  237. {
  238.     struct DisplayInfo DisplayInfo;
  239.     LONG Error;
  240.  
  241.         /* Get the display aspect ratio. */
  242.  
  243.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,GetVPModeID(&Window->WScreen->ViewPort)))
  244.     {
  245.         BitMapHeader Header;
  246.  
  247.             /* Fill in the bitmap header. */
  248.  
  249.         Header.w                = Width;
  250.         Header.h                = Height;
  251.         Header.pageWidth        = Window->WScreen->Width;
  252.         Header.pageHeight        = Window->WScreen->Height;
  253.         Header.x                = Left;
  254.         Header.y                = Top;
  255.         Header.nPlanes            = GetBitMapDepth(Window->WScreen->RastPort.BitMap);
  256.         Header.masking            = mskNone;
  257.         Header.compression        = Compression;
  258.         Header.pad1                = 0;
  259.         Header.transparentColor    = 0;
  260.         Header.xAspect            = DisplayInfo.Resolution.x;
  261.         Header.yAspect            = DisplayInfo.Resolution.y;
  262.  
  263.             /* Push the `BMHD' chunk on the stack. */
  264.  
  265.         if(!(Error = PushChunk(Handle,0,ID_BMHD,sizeof(BitMapHeader))))
  266.         {
  267.                 /* Write the bitmap header. */
  268.  
  269.             if(WriteChunkBytes(Handle,&Header,sizeof(BitMapHeader)) == sizeof(BitMapHeader))
  270.             {
  271.                     /* Pop the `BMHD' chunk. */
  272.  
  273.                 if(!(Error = PopChunk(Handle)))
  274.                     return(TRUE);
  275.             }
  276.             else
  277.                 Error = IoErr();
  278.         }
  279.     }
  280.     else
  281.         Error = ERR_NO_MEM;
  282.  
  283.     if(Error)
  284.         SetIoErr(Error);
  285.  
  286.     return(FALSE);
  287. }
  288.  
  289.     /* PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort):
  290.      *
  291.      *    Output `CMAP' chunk, only 4-bit colour registers
  292.      *    are supported so far.
  293.      */
  294.  
  295. STATIC BOOL
  296. PutCMAP(struct IFFHandle *Handle,struct ViewPort *VPort)
  297. {
  298.     LONG Error;
  299.  
  300.         /* Push the `CMAP' chunk on the stack. */
  301.  
  302.     if(!(Error = PushChunk(Handle,0,ID_CMAP,3 * VPort->ColorMap->Count)))
  303.     {
  304.         ColorRegister Colour;
  305.         LONG i;
  306.  
  307.             /* Read and convert all the
  308.              * ColorMap entries (4 bit colour
  309.              * components only).
  310.              */
  311.  
  312.  
  313.         for(i = 0 ; i < VPort->ColorMap->Count ; i++)
  314.         {
  315.             if(Kick30)
  316.             {
  317.                 ULONG RGB[3];
  318.  
  319.                     /* Read colour value. */
  320.  
  321.                 GetRGB32(VPort->ColorMap,i,1,RGB);
  322.  
  323.                     /* Store the colour components. */
  324.  
  325.                 Colour.red        = RGB[0] >> 24;
  326.                 Colour.green    = RGB[1] >> 24;
  327.                 Colour.blue        = RGB[2] >> 24;
  328.             }
  329.             else
  330.             {
  331.                 ULONG Value;
  332.  
  333.                     /* Read colour value. */
  334.  
  335.                 Value = GetRGB4(VPort->ColorMap,i);
  336.  
  337.                     /* Split the value into components and store them. */
  338.  
  339.                 Colour.red        = ((Value >> 8) & 0xF) * 0x11;
  340.                 Colour.green    = ((Value >> 4) & 0xF) * 0x11;
  341.                 Colour.blue        = ((Value     ) & 0xF) * 0x11;
  342.             }
  343.  
  344.                 /* Write the colours. */
  345.  
  346.             if(WriteChunkBytes(Handle,&Colour,3) != 3)
  347.                 return(FALSE);
  348.         }
  349.  
  350.             /* Pop the `CMAP' chunk. */
  351.  
  352.         if(!(Error = PopChunk(Handle)))
  353.             return(TRUE);
  354.     }
  355.  
  356.     SetIoErr(Error);
  357.  
  358.     return(FALSE);
  359. }
  360.  
  361.     /* PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort):
  362.      *
  363.      *    Output `CAMG' chunk.
  364.      */
  365.  
  366. STATIC BOOL
  367. PutCAMG(struct IFFHandle *Handle,struct ViewPort *VPort)
  368. {
  369.     LONG Error;
  370.  
  371.     if(!(Error = PushChunk(Handle,0,ID_CAMG,sizeof(ULONG))))
  372.     {
  373.         ULONG ViewModes = GetVPModeID(VPort);
  374.  
  375.         if(WriteChunkBytes(Handle,&ViewModes,sizeof(ULONG)) == sizeof(ULONG))
  376.         {
  377.             if(!(Error = PopChunk(Handle)))
  378.                 return(TRUE);
  379.         }
  380.         else
  381.             Error = IoErr();
  382.     }
  383.  
  384.     if(Error)
  385.         SetIoErr(Error);
  386.  
  387.     return(FALSE);
  388. }
  389.  
  390.     /* PutBODY(struct IFFHandle *Handle)
  391.      *
  392.      *    Output `BODY' chunk.
  393.      */
  394.  
  395. STATIC BOOL
  396. PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap,UBYTE Compression)
  397. {
  398.     PLANEPTR *Planes;
  399.     BOOL Success;
  400.     LONG Error;
  401.  
  402.     Success = FALSE;
  403.  
  404.         /* Allocate temporary bitplane pointers. */
  405.  
  406.     if(Planes = (PLANEPTR *)AllocVecPooled(BitMap->Depth * sizeof(PLANEPTR *),MEMF_ANY | MEMF_CLEAR))
  407.     {
  408.         LONG i;
  409.  
  410.             /* Copy the bitplane pointers. */
  411.  
  412.         for(i = 0 ; i < BitMap->Depth ; i++)
  413.             Planes[i] = BitMap->Planes[i];
  414.  
  415.             /* Are we to compress the data? */
  416.  
  417.         if(Compression == cmpByteRun1)
  418.         {
  419.             PLANEPTR PackBuffer;
  420.  
  421.                 /* Allocate line compression buffer. */
  422.  
  423.             if(PackBuffer = (PLANEPTR)AllocVecPooled(BitMap->BytesPerRow * 2,MEMF_ANY))
  424.             {
  425.                     /* Push the `BODY' chunk on the stack. */
  426.  
  427.                 if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  428.                 {
  429.                     LONG PackedBytes,j;
  430.  
  431.                         /* So far, we are quite successful,
  432.                          * any write access to fail will
  433.                          * cause `Success' to drop to FALSE.
  434.                          */
  435.  
  436.                     Success = TRUE;
  437.  
  438.                         /* Compress all the rows. */
  439.  
  440.                     for(i = 0 ; Success && i < BitMap->Rows ; i++)
  441.                     {
  442.                             /* Compress all the planes. */
  443.  
  444.                         for(j = 0 ; Success && j < BitMap->Depth ; j++)
  445.                         {
  446.                                 /* Do the compression. */
  447.  
  448.                             PackedBytes = PackRow(&Planes[j],PackBuffer,BitMap->BytesPerRow);
  449.  
  450.                                 /* Write the compressed data. */
  451.  
  452.                             if(WriteChunkBytes(Handle,PackBuffer,PackedBytes) != PackedBytes)
  453.                             {
  454.                                 Error = IoErr();
  455.  
  456.                                 Success = FALSE;
  457.                             }
  458.                         }
  459.                     }
  460.  
  461.                         /* Pop the `BODY' chunk. */
  462.  
  463.                     if(Success)
  464.                     {
  465.                         if(Error = PopChunk(Handle))
  466.                             Success = FALSE;
  467.                     }
  468.                 }
  469.  
  470.                     /* Free the line compression buffer. */
  471.  
  472.                 FreeVecPooled(PackBuffer);
  473.             }
  474.             else
  475.                 Error = ERR_NO_MEM;
  476.         }
  477.         else
  478.         {
  479.                 /* Push the `BODY' chunk on the stack. */
  480.  
  481.             if(!(Error = PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN)))
  482.             {
  483.                 LONG j;
  484.  
  485.                     /* So far, we are quite successful,
  486.                      * any write access to fail will
  487.                      * cause `Success' to drop to FALSE.
  488.                      */
  489.  
  490.                 Success = TRUE;
  491.  
  492.                     /* Compress all the rows. */
  493.  
  494.                 for(i = 0 ; Success && i < BitMap->Rows ; i++)
  495.                 {
  496.                         /* Compress all the planes. */
  497.  
  498.                     for(j = 0 ; Success && j < BitMap->Depth ; j++)
  499.                     {
  500.                             /* Write the row. */
  501.  
  502.                         if(WriteChunkBytes(Handle,Planes[j],BitMap->BytesPerRow) != BitMap->BytesPerRow)
  503.                         {
  504.                             Error = IoErr();
  505.  
  506.                             Success = FALSE;
  507.                         }
  508.                         else
  509.                             Planes[j] += BitMap->BytesPerRow;
  510.                     }
  511.                 }
  512.  
  513.                     /* Pop the `BODY' chunk. */
  514.  
  515.                 if(Success)
  516.                 {
  517.                     if(Error = PopChunk(Handle))
  518.                         Success = FALSE;
  519.                 }
  520.             }
  521.         }
  522.  
  523.             /* Free the temporary bitplane pointers. */
  524.  
  525.         FreeVecPooled(Planes);
  526.     }
  527.     else
  528.         Error = ERR_NO_MEM;
  529.  
  530.     if(Error)
  531.         SetIoErr(Error);
  532.  
  533.         /* Return the result. */
  534.  
  535.     return(Success);
  536. }
  537.  
  538.     /* SaveWindow(STRPTR Name,struct Window *Window):
  539.      *
  540.      *    Save the contents of a window to a file.
  541.      */
  542.  
  543. BOOL
  544. SaveWindow(STRPTR Name,struct Window *Window)
  545. {
  546.     BOOL Success,NewFile,Locked;
  547.     LONG Error;
  548.  
  549.     Success    = FALSE,
  550.     NewFile    = FALSE,
  551.     Locked    = TRUE;
  552.     Error    = 0;
  553.  
  554.     LockLayerRom(Window->RPort->Layer);
  555.  
  556.         // Datatypes available?
  557.  
  558.     if(DataTypesBase)
  559.     {
  560.         struct BitMap *BitMap;
  561.         struct Screen *Screen;
  562.         LONG Left,Top,Width,Height;
  563.         Object *Picture;
  564.  
  565.         Screen = Window->WScreen;
  566.         Picture = NULL;
  567.  
  568.             // Keep these handy
  569.  
  570.         Left    = Window->LeftEdge    + Window->BorderLeft;
  571.         Top        = Window->TopEdge    + Window->BorderTop;
  572.         Width    = Window->Width        - (Window->BorderLeft + Window->BorderRight);
  573.         Height    = Window->Height    - (Window->BorderTop + Window->BorderBottom);
  574.  
  575.         if(!StatusWindow)
  576.             Height -= StatusDisplayHeight;
  577.  
  578.             // This is where the window contents will go
  579.  
  580.         if(BitMap = AllocBitMap(Width,Height,GetBitMapAttr(Window->RPort->BitMap,BMA_DEPTH),NULL,Window->RPort->BitMap))
  581.         {
  582.             struct RastPort __aligned RPort;
  583.             LONG NumColours;
  584.  
  585.                 // Provide temporary storage
  586.  
  587.             InitRastPort(&RPort);
  588.  
  589.             RPort.BitMap = BitMap;
  590.  
  591.                 // Copy the window contents
  592.  
  593.             ClipBlit(Window->RPort,Window->BorderLeft,Window->BorderTop,&RPort,0,0,Width,Height,MINTERM_COPY);
  594.  
  595.                 // Release the layer
  596.  
  597.             UnlockLayerRom(Window->RPort->Layer);
  598.  
  599.             Locked = FALSE;
  600.  
  601.                 // Wait until all data is transferred
  602.  
  603.             WaitBlit();
  604.  
  605.                 // Get the number of colours available on this screen
  606.  
  607.             NumColours = Screen->ViewPort.ColorMap->Count;
  608.  
  609.                 // Create a picture object
  610.  
  611.             if(Picture = NewDTObject("term image",
  612.                 DTA_SourceType,    DTST_RAM,
  613.                 DTA_GroupID,    GID_PICTURE,
  614.                 PDTA_NumColors,    NumColours,
  615.                 PDTA_BitMap,    BitMap,
  616.                 PDTA_ModeID,    GetVPModeID(&Screen->ViewPort),
  617.             TAG_DONE))
  618.             {
  619.                 struct ColorRegister *ColourMap;
  620.                 struct BitMapHeader *BitMapHeader;
  621.                 ULONG *Colours;
  622.  
  623.                     // Get the internal data arrays
  624.  
  625.                 if(GetDTAttrs(Picture,
  626.                     PDTA_BitMapHeader,        &BitMapHeader,
  627.                     PDTA_ColorRegisters,    &ColourMap,
  628.                     PDTA_CRegs,                &Colours,
  629.                 TAG_DONE) == 3)
  630.                 {
  631.                     LONG i;
  632.  
  633.                         // Fill in the bitmap header
  634.  
  635.                     BitMapHeader->bmh_Left            = Left;
  636.                     BitMapHeader->bmh_Top            = Top;
  637.                     BitMapHeader->bmh_Width            = Width;
  638.                     BitMapHeader->bmh_Height        = Height;
  639.                     BitMapHeader->bmh_Depth            = GetBitMapAttr(BitMap,BMA_DEPTH);
  640.                     BitMapHeader->bmh_PageWidth        = Screen->Width;
  641.                     BitMapHeader->bmh_PageHeight    = Screen->Height;
  642.  
  643.                         // Get the 32 colours
  644.  
  645.                     GetRGB32(Screen->ViewPort.ColorMap,0,NumColours,Colours);
  646.  
  647.                         // Get the 24 bit colours
  648.  
  649.                     for(i = 0 ; i < NumColours ; i++)
  650.                     {
  651.                         ColourMap[i].red    = (UBYTE)(Colours[i * 3 + 0] >> 24);
  652.                         ColourMap[i].green    = (UBYTE)(Colours[i * 3 + 1] >> 24);
  653.                         ColourMap[i].blue    = (UBYTE)(Colours[i * 3 + 2] >> 24);
  654.                     }
  655.                 }
  656.                 else
  657.                 {
  658.                     Error = IoErr();
  659.  
  660.                     DisposeDTObject(Picture);
  661.  
  662.                     Picture = NULL;
  663.                 }
  664.             }
  665.             else
  666.                 Error = IoErr();
  667.         }
  668.         else
  669.             Error = ERROR_NO_FREE_STORE;
  670.  
  671.             // Successful so far?
  672.  
  673.         if(Picture)
  674.         {
  675.             BPTR FileHandle;
  676.  
  677.                 // Open the output file
  678.  
  679.             if(FileHandle = Open(Name,MODE_NEWFILE))
  680.             {
  681.                     // Save the image
  682.  
  683.                 if(DoMethod(Picture,DTM_WRITE,NULL,FileHandle,DTWM_IFF,NULL))
  684.                     Success = TRUE;
  685.                 else
  686.                 {
  687.                     Error = IoErr();
  688.  
  689.                     NewFile = TRUE;
  690.                 }
  691.  
  692.                 Close(FileHandle);
  693.             }
  694.             else
  695.                 Error = IoErr();
  696.  
  697.             DisposeDTObject(Picture);
  698.         }
  699.         else
  700.         {
  701.             if(BitMap)
  702.                 FreeBitMap(BitMap);
  703.         }
  704.     }
  705.     else
  706.     {
  707.         struct RastPort *RPort;
  708.         LONG Depth;
  709.  
  710.             /* Get the depth. */
  711.  
  712.         Depth = GetBitMapDepth(Window->WScreen->RastPort.BitMap);
  713.  
  714.         if(Depth > 8)
  715.         {
  716.             SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  717.  
  718.             return(FALSE);
  719.         }
  720.  
  721.             /* Allocate a dummy rastport, we will need only
  722.              * to copy the contents of the window into the
  723.              * bitmap.
  724.              */
  725.  
  726.         if(RPort = (struct RastPort *)AllocVecPooled(sizeof(struct RastPort),MEMF_ANY))
  727.         {
  728.             struct BitMap *BitMap;
  729.  
  730.                 /* Initialize the rastport with defaults. */
  731.  
  732.             InitRastPort(RPort);
  733.  
  734.                 /* Allocate a bitmap. */
  735.  
  736.             if(BitMap = (struct BitMap *)AllocVecPooled(sizeof(struct BitMap),MEMF_ANY))
  737.             {
  738.                 LONG i,Left,Top,Width,Height;
  739.  
  740.                 Width    = Window->Width        - (Window->BorderLeft + Window->BorderRight);
  741.                 Height    = Window->Height    - (Window->BorderTop + Window->BorderBottom);
  742.                 Left    = Window->LeftEdge    + Window->BorderLeft;
  743.                 Top        = Window->TopEdge    + Window->BorderTop;
  744.  
  745.                 if(!StatusWindow)
  746.                     Height -= StatusDisplayHeight;
  747.  
  748.                     /* Put it into the rastport. */
  749.  
  750.                 RPort->BitMap = BitMap;
  751.  
  752.                     /* Initialize it with the window dimensions. */
  753.  
  754.                 InitBitMap(BitMap,Depth,Width,Height);
  755.  
  756.                     /* Flag success so any allocation
  757.                      * to fail in the bitplane allocation
  758.                      * loop will indicate failure.
  759.                      */
  760.  
  761.                 Success = TRUE;
  762.  
  763.                     /* Allocate all the bitplanes necessary. */
  764.  
  765.                 for(i = 0 ; Success && i < BitMap->Depth ; i++)
  766.                 {
  767.                     if(!(BitMap->Planes[i] = AllocRaster(Width,Height)))
  768.                         Success = FALSE;
  769.                 }
  770.  
  771.                     /* Did we get all the planes we wanted? */
  772.  
  773.                 if(Success)
  774.                 {
  775.                     struct IFFHandle *Handle;
  776.  
  777.                         /* Copy the window contents to the
  778.                          * local bitmap.
  779.                          */
  780.  
  781.                     ClipBlit(Window->RPort,Window->BorderLeft,Window->BorderTop,RPort,0,0,Width,Height,MINTERM_COPY);
  782.  
  783.                         /* Release the lock on the window layer. */
  784.  
  785.                     UnlockLayerRom(Window->RPort->Layer);
  786.  
  787.                         /* Wait for the data to arrive. */
  788.  
  789.                     WaitBlit();
  790.  
  791.                     Locked = FALSE;
  792.  
  793.                         /* Reset the success indicator. */
  794.  
  795.                     Success = FALSE;
  796.  
  797.                         /* Allocate an iff handle. */
  798.  
  799.                     if(Handle = AllocIFF())
  800.                     {
  801.                             /* Open a file for write access. */
  802.  
  803.                         if(Handle->iff_Stream = Open(Name,MODE_NEWFILE))
  804.                         {
  805.                                 /* Remember that we succeeded
  806.                                  * in creating a new file.
  807.                                  */
  808.  
  809.                             NewFile = TRUE;
  810.  
  811.                                 /* Tell iffparse.library that it's
  812.                                  * a plain AmigaDOS file handle.
  813.                                  */
  814.  
  815.                             InitIFFasDOS(Handle);
  816.  
  817.                                 /* Open the file for writing. */
  818.  
  819.                             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  820.                             {
  821.                                     /* Push parent chunk on the
  822.                                      * stack.
  823.                                      */
  824.  
  825.                                 if(!(Error = PushChunk(Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN)))
  826.                                 {
  827.                                         /* Output all the chunk data. */
  828.  
  829.                                     if(PutANNO(Handle))
  830.                                     {
  831.                                         UBYTE Compression;
  832.  
  833.                                             /* Don't compress the bitmap if
  834.                                              * isn't really worth it.
  835.                                              */
  836.  
  837.                                         if(BitMap->BytesPerRow > 4)
  838.                                             Compression = cmpByteRun1;
  839.                                         else
  840.                                             Compression = cmpNone;
  841.  
  842.                                         if(PutBMHD(Handle,Window,Compression,Left,Top,Width,Height))
  843.                                         {
  844.                                             if(PutCMAP(Handle,&Window->WScreen->ViewPort))
  845.                                             {
  846.                                                 if(PutCAMG(Handle,&Window->WScreen->ViewPort))
  847.                                                 {
  848.                                                     if(PutBODY(Handle,BitMap,Compression))
  849.                                                     {
  850.                                                             /* Pop the parent chunk
  851.                                                              * from the stack.
  852.                                                              */
  853.  
  854.                                                         if(!(Error = PopChunk(Handle)))
  855.                                                             Success = TRUE;
  856.                                                     }
  857.                                                     else
  858.                                                         Error = IoErr();
  859.                                                 }
  860.                                                 else
  861.                                                     Error = IoErr();
  862.                                             }
  863.                                             else
  864.                                                 Error = IoErr();
  865.                                         }
  866.                                         else
  867.                                             Error = IoErr();
  868.                                     }
  869.                                     else
  870.                                         Error = IoErr();
  871.                                 }
  872.  
  873.                                     /* Close the iff handle. */
  874.  
  875.                                 CloseIFF(Handle);
  876.                             }
  877.  
  878.                                 /* Close the file. */
  879.  
  880.                             if(!Close(Handle->iff_Stream))
  881.                             {
  882.                                 Error = IoErr();
  883.  
  884.                                 Success = FALSE;
  885.                             }
  886.                         }
  887.                         else
  888.                             Error = IoErr();
  889.  
  890.                             /* Free the iff handle. */
  891.  
  892.                         FreeIFF(Handle);
  893.                     }
  894.                     else
  895.                         Error = ERR_NO_MEM;
  896.                 }
  897.                 else
  898.                     Error = ERR_NO_MEM;
  899.  
  900.                     /* Free all bitplanes. */
  901.  
  902.                 for(i = 0 ; i < BitMap->Depth ; i++)
  903.                 {
  904.                     if(BitMap->Planes[i])
  905.                         FreeRaster(BitMap->Planes[i],Width,Height);
  906.                 }
  907.  
  908.                     /* Free the bitmap. */
  909.  
  910.                 FreeVecPooled(BitMap);
  911.             }
  912.             else
  913.                 Error = ERR_NO_MEM;
  914.  
  915.                 /* Free the rastport. */
  916.  
  917.             FreeVecPooled(RPort);
  918.         }
  919.         else
  920.             Error = ERR_NO_MEM;
  921.     }
  922.  
  923.         /* Release the window layer in case it is still locked. */
  924.  
  925.     if(Locked)
  926.         UnlockLayerRom(Window->RPort->Layer);
  927.  
  928.         /* If successful, clear the `executable' bit. */
  929.  
  930.     if(Success)
  931.     {
  932.         AddProtection(Name,FIBF_EXECUTE);
  933.  
  934.         if(Config->MiscConfig->CreateIcons)
  935.             AddIcon(CaptureName,FILETYPE_PICTURE,TRUE);
  936.     }
  937.     else
  938.     {
  939.             /* Delete the remains of the file. */
  940.  
  941.         if(NewFile)
  942.             DeleteFile(Name);
  943.  
  944.         SetIoErr(Error);
  945.     }
  946.  
  947.         /* Return the result. */
  948.  
  949.     return(Success);
  950. }
  951.